package com.laolei.core.rest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.laolei.core.exception.GlobalException;
import com.laolei.core.exception.GlobalExceptionStatus;
import com.laolei.core.logging.RunTimeLog;
import com.laolei.core.model.Entity;
import com.laolei.core.utils.StringUtils;

@Component
public class InvokeHandle {

	private final static Logger LOGGER = LoggerFactory.getLogger(InvokeHandle.class);
	HttpRequestHandle httpRequestHandle = new HttpRequestHandle();
	ObjectMapper objectMapper = new ObjectMapper();

	public Object doHttpInvoke(ProxyInvoke proxyInvoke, Object[] args, RestClientData resttData) throws Throwable {

		RunTimeLog.log("方法 {} 请求开始  ", resttData.getMethodKey());
		httpRequestHandle.handle(resttData, args);
		RunTimeLog.log("方法 {} 请求结束 响应的数据:{}", resttData.getMethodKey(), HttpContext.getResponse());
		try {
			if (resttData.isManuallyprocessed())
				return proxyInvoke.invoke();
			return this.autoReturn(resttData);
		} finally {
			HttpContext.getCurrentResponse().close();
		}
	}

	@SuppressWarnings("unchecked")
	private Object autoReturn(RestClientData resttData) {
		Throwable ex = HttpContext.getException();
		if (ex != null)
			GlobalException.throwException(GlobalExceptionStatus.DO_REQUEST_FAIL, ex);
		if (!HttpContext.isOk())
			GlobalException.throwException(GlobalExceptionStatus.DO_REQUEST_FAIL);
		try {
			String relust = HttpContext.getBody();
			if (StringUtils.isEmpty(relust))
				return null;
			Object ret = objectMapper.readValue(relust, resttData.getReturnType());
			if (ret != null && resttData.isUnpack()) {
				this.check((Entity<Object>) ret);
				return ((Entity<Object>) ret).getEntity();
			}
			return ret;
		} catch (Throwable e) {
			LOGGER.error("发请求，结果集转化为json失败");
			GlobalException.throwException(GlobalExceptionStatus.DO_REQUEST_DESERIALIZATION_FAIL, e);
			return null;
		}
	}

	private void check(Entity<Object> entity) {
		if (entity == null || entity.isOk())
			return;
		GlobalException globalException = new GlobalException(GlobalExceptionStatus.FAIL);
		globalException.setCode(entity.getCode());
		globalException.setLevel(entity.getLevel());
		globalException.setDescribe(entity.getMessage());
		globalException.setDetails(entity.getDetails());
		globalException.setGoUrl(entity.getGoUrl());
		throw globalException;
	}

}
